import * as fse from 'fs-extra';
import { Log, ILoggable } from '../utils/Log';

/**
 * interface of reader
 */
export interface IReader {
    getType(): string;
    readFromFile<T>(filepath: string, encoding: BufferEncoding): Promise<T | undefined>;
}

/**
 * base reader
 */
export abstract class BaseReader implements ILoggable, IReader {
    public readonly DOMAIN: string;
    public readonly TAG: string;
    protected type: string;
    /**
     * get type
     * @returns type
     */
    public getType(): string {
        return this.type;
    }

    /**
     * write to file
     * @param file filepath
     * @param data data
     * @returns T | undefined
     */
    public async readFromFile<T>(
        filepath: string, 
        encoding: BufferEncoding = 'utf-8'): Promise<T | undefined> {
        return undefined;
    }
}

/**
 * JsonReader
 */
export class JsonReader extends BaseReader {
    public readonly DOMAIN: string;
    public readonly TAG: string;
    protected type: string;
    private static _instance: JsonReader;

    constructor() {
        super()
        this.DOMAIN = 'meminsight';
        this.TAG = JsonReader.name;
        this.type = JsonReader.name;
    }

    /**
     * JsonReader instance
     * @returns instance
     */
    public static instance(): JsonReader {
        if (!JsonReader._instance) {
            JsonReader._instance = new JsonReader();
        }
        return JsonReader._instance;
    }

    /**
     * read json file
     * @param filepath json file path
     * @param encode encoding, default is utf-
     * @returns T | undefined
     */
    public async readFromFile<T>(filepath: string, 
        encoding: BufferEncoding = 'utf-8') : Promise<T | undefined> {
        try {
            return fse.readJSONSync(filepath, encoding) as T;
        } catch (error) {
            Log.errorX(this, `Failed to read json from file, Status Code: ${error}`)
            return undefined;
        }
    }
}